from readlater.utils.logger import get_logger
from readlater.database import DatabaseManager
from readlater.config import ConfigManager
from playwright.sync_api import sync_playwright
from random import randint
import time

class WebpageVisitor:

    def __init__(self):
        self.logger = get_logger(__name__)
        self.config = ConfigManager()
        self.db_manager = DatabaseManager(self.config.get_database_path())

    def search_download_list(self):
        """
        从todo_list表中查询status为link_extracted的文章
        """

        self.db_manager.connect()
        articles = self.db_manager.get_articles_by_status(
            DatabaseManager.STATUS_LINK_EXTRACTED)
        self.db_manager.close()
        return articles

    def _download_webpage(self, url: str, wait_time: int = 5, browser_type: str = "chromium"):

        """
        下载网页内容
        """
        with sync_playwright() as p:
            if browser_type == "chromium":
                browser = p.chromium.launch(headless=False)
            elif browser_type == "firefox":
                browser = p.firefox.launch(headless=False)
            else:
                browser = p.chromium.launch(headless=False)

            page = browser.new_page(
                user_agent=self.config.get("scraping.user_agent"))

            try:
                page.goto(url)
                page.wait_for_load_state("load")
                if wait_time:
                        page.wait_for_timeout(wait_time*1000)
                
            except:
                    self.logger.error(f"下载{url}超时(等待{wait_time}秒)，尝试下载部分内容")
            finally:
                content = page.inner_text("body")

            browser.close()
            return content

    def download_webpages(self, articles: list):
        """
        下载多篇文章
        """
        save_path = self.config.get_save_path()
        time_period = int(self.config.get("scraping.time_period"))
        download_wait_time = int(
            self.config.get("scraping.download_wait_time"))

        success_list = []
        failed_list = []
        for article in articles:
            url = article.get("url")
            id = article.get("id")
            title = article.get("title")
            filename = f"{id}.txt"
            content = self._download_webpage(url, wait_time=download_wait_time)
            if not self._is_download_successed(content):
                content = self._download_webpage(url, wait_time=download_wait_time, browser_type="firefox")
                if not self._is_download_successed(content):
                    self.logger.error(f"下载文章<{title}>内容失败")
                    failed_list.append(article)
                    continue

            try:
                with open(f"{save_path}/{filename}", "w", encoding="utf-8") as f:
                    f.write(content)

                self.logger.info(f"保存文章<{title}>内容到{save_path}/{filename}")
                self._update_article_status_downloaded(
                    article_id=id, file_name=filename)
                success_list.append(article)
            except Exception as e:
                self.logger.error(
                    f"保存文章<{title}>内容到{save_path}/{filename}失败: {e}")
                failed_list.append(article)

            # 随机等待1~N秒
            wait_time = randint(1, time_period)
            self.logger.info(f"等待{wait_time}秒后继续下载下一篇文章")
            time.sleep(wait_time)

        return success_list, failed_list

    def _is_download_successed(self, content: str):
        """
        判断下载是否失败
        """
        if not content:
            return False

        content_stipped = content.strip()

        if not content_stipped:
            return False

        if content_stipped.replace('\n', '').startswith('环境异常当前环境异常，完成验证后即可继续访问。去验证'):
            return False

        return True

    def _update_article_status_downloaded(self, article_id: str, file_name: str, in_transaction: bool = False):
        """
        更新文章状态
        """
        status = DatabaseManager.STATUS_CONTENT_DOWNLOADED
        query = "UPDATE todo_list SET status = ?, file_name = ? WHERE id = ?"

        if not in_transaction:
            self.db_manager.connect()

        try:
            self.db_manager.cursor.execute(
                query, (status, file_name, article_id))
            self.logger.info(f"更新文章{article_id}状态为{status}, 文件名{file_name}")
            if not in_transaction:
                self.db_manager.conn.commit()
        except Exception as e:
            self.logger.error(f"更新文章{article_id}状态失败: {e}")
            if not in_transaction:
                self.db_manager.conn.rollback()
            raise e
        finally:
            self.db_manager.close()

    def _begin_transaction(self):
        self.db_manager.connect()
        self.db_manager.begin_transaction()
        self.logger.info("开始事务")

    def _end_transaction(self):
        self.db_manager.conn.commit()
        self.db_manager.close()
        self.logger.info("结束事务")

    def _rollback_transaction(self):
        self.db_manager.conn.rollback()
        self.db_manager.close()
        self.logger.info("回滚事务")
